#!/usr/bin/env python

__author__ = "Juan C. Montes"
__credits__ = ["Marcos Orallo", "Juan C. Montes"]
__license__ = "GPL"
__version__ = "0.0.1"
__maintainer__ = "Juan C. Montes"
__email__ = "jcmontes.tec@gmail.com"


# Ogre3D References
import ogre.renderer.OGRE as ogre
import ogre.io.OIS as ois

# Project References
from character import character
from menu import menu


class greyhat(ogre.FrameListener, ois.KeyListener):
    """Main Game Class.
    
Manage all data in game.
    """
        
    def __init__(self):
        """Default constructor"""
        # Properties
        self.mainmenu = menu
        
        # Game state
        self.quit = False
        self.pause = False
        self.wait = True 
        self.time = 0   
        pass
    
    def go(self):
        """Main function"""
        self.createRoot()
        self.setupRenderSystem()
        self.createRenderWindow()        
        self.setupScene()
        self.setupInputSystem()
        self.createFrameListener()
        self.initialiseResourceGroups()
        self.createMainMenu()
        self.startRenderLoop()
        pass
    
    def createRoot(self):
        """Function to create the root engine"""
        self.root = ogre.Root()
        pass
        
    def setupRenderSystem(self):    
        """Load the store config or show the config menu"""
        if not self.root.restoreConfig() and not self.root.showConfigDialog():
            raise Exception("User canceled the config dialog!" 
                            "-> Application.setupRenderSystem()")
        pass

    def createRenderWindow(self):
        """Create the main window"""
        self.window = self.root.initialise(True, "GreyHat v0.0.1")
        pass

    def initialiseResourceGroups(self):
        """Load all game resources"""        
        ogre.ResourceGroupManager.getSingleton().addResourceLocation(
                "./media/", "FileSystem", "GreyHat")
        ogre.ResourceGroupManager.getSingleton().initialiseAllResourceGroups()
        pass

    def setupScene(self):
        """Prepare the main scene(cameras, lights, viewports...)"""
        # Create the SceneManager
        self.scenemanager = ogre.SceneManager
        self.scenemanager = self.root.createSceneManager(ogre.ST_GENERIC)
        
        # Create and move the main camera
        self.camera = ogre.Camera
        self.camera = self.scenemanager.createCamera("MainCamera")
        self.camera.setPosition(0, 0, 240)
        self.camera.lookAt(0, 0, 0)
        self.camera.setNearClipDistance(5)
        self.camera.setFarClipDistance(1000)
        
        # Create the view port with camera based
        self.pViewport = ogre.Viewport
        self.pViewport = self.window.addViewport(self.camera)
        self.pViewport.setBackgroundColour(ogre.ColourValue(0, 0, 0))
        self.camera.setAspectRatio(self.pViewport.getActualWidth() / 
                                   self.pViewport.getActualHeight())
        
        # Set the scene lights
        self.scenemanager.setAmbientLight(ogre.ColourValue(0.75, 0.75, 0.75))
        
        # Create the light 
        self.light = ogre.Light
        self.light = self.scenemanager.createLight("Light")
        self.light.setPosition(0, 0, 50)
        pass

    def setupInputSystem(self):
        """Prepare the keyboard controls"""
        windowHandle = 0
        renderWindow = self.root.getAutoCreatedWindow()
        windowHandle = renderWindow.getCustomAttributeInt("WINDOW")
        paramList = [("WINDOW", str(windowHandle))]
        self.inputManager = ois.createPythonInputSystem(paramList)
        try:
            self.keyboard = self.inputManager.createInputObjectKeyboard(
                            ois.OISKeyboard, True)
        except Exception, e:
            raise e
        pass

    def createFrameListener(self):       
        """Initialize the main listener and the keyboard listener""" 
        ois.KeyListener.__init__(self) 
        ogre.FrameListener.__init__(self)
        self.root.addFrameListener(self)
        pass
        
    def startRenderLoop(self):   
        """Start the game loop"""         
        self.root.startRendering()

    def cleanUp(self):
        """Destroy the created objects"""
        try:
            self.inputManager
            self.inputManager.destroyInputObjectKeyboard(self.keyboard)
            ois.InputManager.destroyInputSystem(self.inputManager)
            self.inputManager = None
        except Exception, e:
            raise e
        pass
        
    def __del__(self):
        """Destructor"""
        self.cleanUp()
        pass
        
    def createMainMenu(self):
        """Create and setup the main menu"""
        # Show the main menu
        self.mainmenu = menu(self.pViewport.getActualWidth(),
                             self.pViewport.getActualHeight())
        self.mainmenu.createMenu(self.window, self.scenemanager)
        self.mainmenu.createSceneMenu()
        self.mainmenu.addNewItem("New Game")
        self.mainmenu.addNewItem("Restore Game")
        self.mainmenu.addNewItem("Options")
        self.mainmenu.addNewItem("Credits")
        self.mainmenu.addNewItem("Exit")                
        pass


    def frameStarted(self, e):
        """Rendering control"""
        # Capture the keyboard
        self.keyboard.capture()
        
        # Check the keyboard buffer
        if self.keyboard.buffered():
            self.processKeyBuffered()
                
        # Check the game state
        if not self.wait and not self.pause:
            pass
            
        elif self.wait:
            # Do a wait for 4 seconds
            if self.time < 4:
                self.time += e.timeSinceLastFrame
            else:
                self.wait = False
                self.time = 0
                
        return not self.quit
    
    def processKeyBuffered(self):
        """Check the keyboard buffer"""
        # Check the game state
        if not self.pause:
            # Check the key down
            if self.keyboard.isKeyDown(ois.KC_ESCAPE):
                self.quit = True
                self.root.shutdown()
        pass            